Python iteratsiyasi imkoniyatlarini oching. __iter__ va __next__ metodlari yordamida maxsus iteratorlarni tatbiq etish bo'yicha amaliy, real misollar bilan global dasturchilar uchun to'liq qo'llanma.
Python-ning Iterator Protokolini Tushunish: __iter__ va __next__ metodlariga chuqur nazar
Iteratsiya - dasturlashdagi eng asosiy tushunchalardan biridir. Python-da bu oddiy for sikllaridan tortib murakkab ma'lumotlarni qayta ishlash quvurlarigacha bo'lgan hamma narsani quvvatlaydigan nafis va samarali mexanizmdir. Siz uni har kuni ro'yxatni aylanib chiqishda, fayldan qatorlarni o'qishda yoki ma'lumotlar bazasi natijalari bilan ishlashda ishlatasiz. Lekin siz hech o'ylab ko'rganmisiz, bu jarayon qanday ishlaydi? Python qanday qilib shuncha ko'p turli xil ob'ektlardan 'keyingi' elementni olishni biladi?
Javob Iterator Protokoli deb nomlanuvchi kuchli va nafis dizayn naqshida yotadi. Ushbu protokol Python-ning barcha ketma-ketlikka o'xshash ob'ektlari gaplashadigan umumiy tildir. Ushbu protokolni tushunib, uni amalga oshirish orqali siz Python-ning iteratsiya vositalariga to'liq mos keladigan o'zingizning maxsus ob'ektlaringizni yaratishingiz mumkin, bu esa kodingizni yanada ifodali, xotirani tejaydigan va asl 'Pythonic' qiladi.
Ushbu keng qamrovli qo'llanma sizni iterator protokoli bo'yicha chuqur sayohatga olib chiqadi. Biz `__iter__` va `__next__` metodlari ortidagi sehrni ochib beramiz, iterable va iterator o'rtasidagi muhim farqni aniqlashtiramiz va sizga noldan o'z maxsus iteratorlaringizni yaratishda yordam beramiz. Siz Python-ning ichki tuzilishini chuqurroq tushunishni istagan o'rta darajadagi dasturchi bo'lasizmi yoki yanada murakkab API-larni loyihalashni maqsad qilgan mutaxassis bo'lasizmi, iterator protokolini o'zlashtirish sizning yo'lingizdagi muhim qadamdir.
'Nima uchun': Iteratsiyaning ahamiyati va kuchi
Texnik amalga oshirishga sho'ng'ishdan oldin, iterator protokolining nima uchun bunchalik muhimligini tushunish zarur. Uning afzalliklari shunchaki `for` sikllarini yoqishdan ancha yuqori turadi.
Xotira Samaradorligi va Yolg'onchi Baholash (Lazy Evaluation)
Tasavvur qiling, siz bir necha gigabayt hajmdagi ulkan log faylini qayta ishlashingiz kerak. Agar siz butun faylni xotiradagi ro'yxatga o'qisangiz, tizimingiz resurslarini tugatib qo'yishingiz mumkin. Iteratorlar bu muammoni yolg'onchi baholash (lazy evaluation) deb nomlangan tushuncha orqali go'zal hal qiladi.
Iterator barcha ma'lumotlarni bir vaqtning o'zida yuklamaydi. Buning o'rniga, u bir vaqtning o'zida, faqat so'ralganda bitta elementni yaratadi yoki olib keladi. U ketma-ketlikda qayerda ekanligini eslab qolish uchun ichki holatni saqlaydi. Bu shuni anglatadiki, siz (nazariy jihatdan) cheksiz katta ma'lumotlar oqimini juda kichik, doimiy miqdordagi xotira bilan qayta ishlashingiz mumkin. Bu sizga dasturingizni ishdan chiqarmasdan katta faylni qatorma-qator o'qish imkonini beradigan xuddi shu printsipdir.
Toza, O'qilishi Oson va Universal Kod
Iterator protokoli ketma-ket kirish uchun universal interfeysni taqdim etadi. Ro'yxatlar, kortezhlar, lug'atlar, satrlar, fayl ob'ektlari va boshqa ko'plab turlar ushbu protokolga amal qilganligi sababli, siz ularning barchasi bilan ishlash uchun bir xil sintaksisdan - `for` siklidan foydalanishingiz mumkin. Bu bir xillik Python-ning o'qilishi osonligining tamal toshidir.
Ushbu kodni ko'rib chiqing:
Kod:
my_list = [1, 2, 3]
for item in my_list:
print(item)
my_string = "abc"
for char in my_string:
print(char)
with open('my_file.txt', 'r') as f:
for line in f:
print(line)
`for` sikli butun sonlar ro'yxati, belgilar satri yoki fayldan olingan qatorlar ustida iteratsiya qilayotganiga parvo qilmaydi. U shunchaki ob'ektdan uning iteratorini so'raydi va keyin iteratordan qayta-qayta keyingi elementini so'raydi. Bu abstraktsiya nihoyatda kuchlidir.
Iterator Protokolini Tahlil Qilish
Protokolning o'zi ajablanarli darajada oddiy bo'lib, faqat ikkita maxsus metod bilan belgilanadi, ularni ko'pincha "dunder" (double underscore - qo'sh pastki chiziq) metodlari deb atashadi:
- `__iter__()`
- `__next__()`
Bularni to'liq tushunish uchun biz avvalo bir-biriga bog'liq, ammo farqli bo'lgan ikkita tushunchani: iterable va iteratorni farqlashimiz kerak.
Iterable va Iterator: Muhim Farq
Bu ko'pincha yangi boshlovchilar uchun chalkashlik nuqtasi bo'ladi, ammo farq juda muhim.
Iterable nima?
Iterable - bu ustidan sikl orqali o'tish mumkin bo'lgan har qanday ob'ekt. Bu iterator olish uchun o'rnatilgan `iter()` funksiyasiga uzatishingiz mumkin bo'lgan ob'ekt. Texnik jihatdan, agar ob'ekt `__iter__` metodini amalga oshirsa, u iterable hisoblanadi. Uning `__iter__` metodining yagona maqsadi iterator ob'ektini qaytarishdir.
O'rnatilgan iterablelarga misollar:
- Ro'yxatlar (`[1, 2, 3]`)
- Kortezhlar (`(1, 2, 3)`)
- Satrlar (`"hello"`)
- Lug'atlar (`{'a': 1, 'b': 2}` - kalitlar bo'yicha iteratsiya qiladi)
- To'plamlar (`{1, 2, 3}`)
- Fayl ob'ektlari
Siz iterable ob'ektni konteyner yoki ma'lumot manbai deb o'ylashingiz mumkin. U elementlarni o'zi qanday ishlab chiqarishni bilmaydi, lekin buni qila oladigan ob'ektni - iteratorni qanday yaratishni biladi.
Iterator nima?
Iterator - bu iteratsiya davomida qiymatlarni amalda ishlab chiqarish ishini bajaradigan ob'ekt. U ma'lumotlar oqimini ifodalaydi. Iterator ikkita metodni amalga oshirishi kerak:
- `__iter__()`: Ushbu metod iterator ob'ektining o'zini (`self`) qaytarishi kerak. Bu iteratorlarni iterablelar kutilgan joylarda, masalan, `for` siklida ham ishlatish mumkin bo'lishi uchun talab qilinadi.
- `__next__()`: Ushbu metod iteratorning dvigatelidir. U ketma-ketlikdagi keyingi elementni qaytaradi. Qaytariladigan elementlar qolmaganda, u `StopIteration` istisnosini ko'tarishi shart. Bu istisno xato emas; bu iteratsiyaning tugaganligini sikl konstruksiyasiga bildiruvchi standart signaldir.
Iteratorning asosiy xususiyatlari:
- Holatni saqlaydi: Iterator ketma-ketlikdagi joriy pozitsiyasini eslab qoladi.
- Qiymatlarni birma-bir ishlab chiqaradi: `__next__` metodi orqali.
- Tugatib bo'linadi: Iterator to'liq iste'mol qilinganidan so'ng (ya'ni, u `StopIteration` ko'targanidan so'ng), u bo'sh bo'ladi. Siz uni qayta o'rnatolmaysiz yoki qayta ishlata olmaysiz. Yana iteratsiya qilish uchun siz asl iterable ob'ektga qaytib, unda `iter()` funksiyasini qayta chaqirib, yangi iterator olishingiz kerak.
Birinchi Maxsus Iteratorimizni Yaratish: Qadamma-qadam Qo'llanma
Nazariya ajoyib, ammo protokolni tushunishning eng yaxshi usuli - uni o'zingiz yaratishdir. Keling, hisoblagich vazifasini bajaradigan, boshlang'ich sondan chegaragacha iteratsiya qiladigan oddiy klass yaratamiz.
1-misol: Oddiy Hisoblagich Klassi
Biz `CountUpTo` deb nomlangan klass yaratamiz. Uning nusxasini yaratganingizda, siz maksimal sonni belgilaysiz va uning ustida iteratsiya qilganingizda, u 1 dan o'sha maksimal songacha bo'lgan sonlarni beradi.
Kod:
class CountUpTo:
"""Belgilangan maksimal songacha 1 dan sanaydigan iterator."""
def __init__(self, max_num):
print("CountUpTo ob'ektini ishga tushirish...")
self.max_num = max_num
self.current = 0 # Bu holatni saqlaydi
def __iter__(self):
print("__iter__ chaqirildi, self qaytarilmoqda...")
# Bu ob'ekt o'zining iteratori, shuning uchun self qaytaramiz
return self
def __next__(self):
print("__next__ chaqirildi...")
if self.current < self.max_num:
self.current += 1
return self.current
else:
# Bu eng muhim qism: tugaganligimizni bildiramiz.
print("StopIteration ko'tarilmoqda.")
raise StopIteration
# Uni qanday ishlatish kerak
print("Hisoblagich ob'ektini yaratish...")
counter = CountUpTo(3)
print("\nfor siklini boshlash...")
for number in counter:
print(f"For sikli qabul qildi: {number}")
Kod Tahlili va Izohi
`for` sikli ishlaganda nima sodir bo'lishini tahlil qilaylik:
- Ishga tushirish: `counter = CountUpTo(3)` klassimizning nusxasini yaratadi. `__init__` metodi ishga tushib, `self.max_num` ni 3 ga va `self.current` ni 0 ga o'rnatadi. Ob'ektimizning holati endi ishga tushirildi.
- Siklni boshlash: `for number in counter:` qatoriga yetganda, Python ichkaridan `iter(counter)` ni chaqiradi.
- `__iter__` chaqiriladi: `iter(counter)` chaqiruvi bizning `counter.__iter__()` metodimizni ishga tushiradi. Kodimizdan ko'rinib turibdiki, bu metod shunchaki xabar chiqaradi va `self` ni qaytaradi. Bu `for` sikliga: "Siz `__next__` ni chaqirishingiz kerak bo'lgan ob'ekt - bu men!" deb aytadi.
- Sikl boshlanadi: Endi `for` sikli tayyor. Har bir iteratsiyada u olgan iterator ob'ektida (bu bizning `counter` ob'ektimiz) `next()` ni chaqiradi.
- Birinchi `__next__` chaqiruvi: `counter.__next__()` metodi chaqiriladi. `self.current` 0 ga teng, bu `self.max_num` (3) dan kichik. Kod `self.current` ni 1 ga oshiradi va uni qaytaradi. `for` sikli bu qiymatni `number` o'zgaruvchisiga belgilaydi va sikl tanasi (`print(...)`) bajariladi.
- Ikkinchi `__next__` chaqiruvi: Sikl davom etadi. `__next__` yana chaqiriladi. `self.current` 1 ga teng. U 2 ga oshiriladi va qaytariladi.
- Uchinchi `__next__` chaqiruvi: `__next__` yana chaqiriladi. `self.current` 2 ga teng. U 3 ga oshiriladi va qaytariladi.
- Oxirgi `__next__` chaqiruvi: `__next__` yana bir marta chaqiriladi. Endi `self.current` 3 ga teng. `self.current < self.max_num` sharti yolg'on. `else` bloki bajariladi va `StopIteration` ko'tariladi.
- Siklni tugatish: `for` sikli `StopIteration` istisnosini ushlash uchun mo'ljallangan. Buni qilganda, u iteratsiyaning tugaganini biladi va chiroyli tarzda tugaydi. Dastur sikldan keyingi har qanday kodni bajarishda davom etadi.
Muhim bir detalga e'tibor bering: agar siz xuddi shu `counter` ob'ektida `for` siklini yana ishga tushirishga harakat qilsangiz, u ishlamaydi. Iterator tugagan. `self.current` allaqachon 3 ga teng, shuning uchun `__next__` ga keyingi har qanday chaqiruv darhol `StopIteration` ni ko'taradi. Bu bizning ob'ektimiz o'zining iteratori bo'lishining oqibatidir.
Ilg'or Iterator Tushunchalari va Haqiqiy Dunyo Ilovalari
Oddiy hisoblagichlar o'rganish uchun ajoyib usul, ammo iterator protokolining haqiqiy kuchi yanada murakkab, maxsus ma'lumotlar tuzilmalariga qo'llanilganda namoyon bo'ladi.
Iterable va Iteratorni Birlashtirishdagi Muammo
Bizning `CountUpTo` misolimizda klass ham iterable, ham iterator edi. Bu oddiy, ammo katta kamchilikka ega: natijadagi iterator tugatib bo'linadigan. Bir marta uning ustidan aylanib chiqsangiz, u tugaydi.
Kod:
counter = CountUpTo(2)
print("Birinchi iteratsiya:")
for num in counter: print(num) # Yaxshi ishlaydi
print("\nIkkinchi iteratsiya:")
for num in counter: print(num) # Hech narsa chiqarmaydi!
Buning sababi, holat (`self.current`) ob'ektning o'zida saqlanadi. Birinchi sikldan so'ng, `self.current` 2 ga teng bo'ladi va keyingi `__next__` chaqiruvlari shunchaki `StopIteration` ni ko'taradi. Bu xatti-harakat siz bir necha marta iteratsiya qilishingiz mumkin bo'lgan standart Python ro'yxatidan farq qiladi.
Yanada Mustahkam Naqsh: Iterable-ni Iterator-dan Ajratish
Python-ning o'rnatilgan to'plamlari kabi qayta ishlatiladigan iterable-larni yaratish uchun eng yaxshi amaliyot bu ikki rolni ajratishdir. Konteyner ob'ekti iterable bo'ladi va uning `__iter__` metodi har safar chaqirilganda yangi, toza iterator ob'ektini yaratadi.
Keling, misolimizni ikkita klassga qayta tuzamiz: `Sentence` (iterable) va `SentenceIterator` (iterator).
Kod:
class SentenceIterator:
"""Holat va qiymatlarni ishlab chiqarish uchun mas'ul iterator."""
def __init__(self, words):
self.words = words
self.index = 0
def __next__(self):
try:
word = self.words[self.index]
except IndexError:
raise StopIteration()
self.index += 1
return word
def __iter__(self):
# Iterator ham iterable bo'lishi kerak, o'zini qaytaradi.
return self
class Sentence:
"""Iterable konteyner klassi."""
def __init__(self, text):
# Konteyner ma'lumotlarni saqlaydi.
self.words = text.split()
def __iter__(self):
# __iter__ har safar chaqirilganda, u YANGI iterator ob'ektini yaratadi.
return SentenceIterator(self.words)
# Uni qanday ishlatish kerak
my_sentence = Sentence('Bu bir sinov')
print("Birinchi iteratsiya:")
for word in my_sentence:
print(word)
print("\nIkkinchi iteratsiya:")
for word in my_sentence:
print(word)
Endi u xuddi ro'yxat kabi ishlaydi! Har safar `for` sikli boshlanganda, u `my_sentence.__iter__()` ni chaqiradi, bu esa o'zining holatiga (`self.index = 0`) ega bo'lgan yangi `SentenceIterator` nusxasini yaratadi. Bu bir xil `Sentence` ob'ekti ustida bir nechta, mustaqil iteratsiyalarga imkon beradi. Ushbu naqsh ancha mustahkamroq va Python-ning o'z to'plamlari shunday amalga oshirilgan.
Misol: Cheksiz Iteratorlar
Iteratorlar cheklangan bo'lishi shart emas. Ular cheksiz ma'lumotlar ketma-ketligini ifodalashi mumkin. Aynan shu yerda ularning dangasa, birma-bir ishlash tabiati katta afzallik beradi. Keling, Fibonachchi sonlarining cheksiz ketma-ketligi uchun iterator yaratamiz.
Kod:
class FibonacciIterator:
"""Fibonachchi sonlarining cheksiz ketma-ketligini yaratadi."""
def __init__(self):
self.a, self.b = 0, 1
def __iter__(self):
return self
def __next__(self):
result = self.a
self.a, self.b = self.b, self.a + self.b
return result
# Uni qanday ishlatish kerak - EHTIYOT BO'LING: to'xtatmasdan cheksiz sikl!
fib_gen = FibonacciIterator()
for i, num in enumerate(fib_gen):
print(f"Fibonacci({i}): {num}")
if i >= 10: # Biz to'xtash shartini ta'minlashimiz kerak
break
Ushbu iterator hech qachon o'z-o'zidan `StopIteration` ni ko'tarmaydi. Siklni tugatish uchun shart (masalan, `break` iborasi) ta'minlash chaqiruvchi kodning mas'uliyatidir. Ushbu naqsh ma'lumotlar oqimi, hodisalar sikllari va raqamli simulyatsiyalarda keng tarqalgan.
Iterator Protokoli Python Ekotizimida
`__iter__` va `__next__` ni tushunish sizga ularning Python-da hamma joyda ta'sirini ko'rish imkonini beradi. Bu Python-ning ko'plab xususiyatlarining bir-biri bilan uzluksiz ishlashini ta'minlaydigan birlashtiruvchi protokoldir.
`for` Sikllari *Aslida* Qanday Ishlaydi
Biz buni bilvosita muhokama qildik, lekin keling, aniqlashtiramiz. Python ushbu qatorga duch kelganda:
`for item in my_iterable:`
U sahna ortida quyidagi amallarni bajaradi:
- Iterator olish uchun `iter(my_iterable)` ni chaqiradi. Bu o'z navbatida `my_iterable.__iter__()` ni chaqiradi. Qaytarilgan ob'ektni `iterator_obj` deb ataylik.
- U cheksiz `while True` sikliga kiradi.
- Sikl ichida u `next(iterator_obj)` ni chaqiradi, bu o'z navbatida `iterator_obj.__next__()` ni chaqiradi.
- Agar `__next__` qiymat qaytarsa, u `item` o'zgaruvchisiga belgilanadi va `for` sikli bloki ichidagi kod bajariladi.
- Agar `__next__` `StopIteration` istisnosini ko'tarsa, `for` sikli bu istisnoni ushlaydi va o'zining ichki `while` siklidan chiqadi. Iteratsiya tugallanadi.
Comprehensions va Generator Expressions
Ro'yxat, to'plam va lug'at komprehenshnlari (list, set, and dictionary comprehensions) barchasi iterator protokoli tomonidan quvvatlanadi. Siz yozganingizda:
`squares = [x * x for x in range(10)]`
Python samarali ravishda `range(10)` ob'ekti ustida iteratsiya qilmoqda, har bir qiymatni olib, ro'yxatni yaratish uchun `x * x` ifodasini bajarmoqda. Xuddi shu narsa generator ifodalari (generator expressions) uchun ham to'g'ri keladi, bu esa dangasa iteratsiyadan yanada to'g'ridan-to'g'ri foydalanishdir:
`lazy_squares = (x * x for x in range(1000000))`
Bu xotirada million elementli ro'yxat yaratmaydi. U iterator (aniqrog'i, generator ob'ekti) yaratadi, bu esa siz uning ustida iteratsiya qilganingizda kvadratlarni birma-bir hisoblab beradi.
Generatorlar: Iteratorlarni Yaratishning Oddiyroq Usuli
`__iter__` va `__next__` bilan to'liq klass yaratish sizga maksimal nazoratni bergan bo'lsa-da, oddiy holatlar uchun u ko'p so'zli bo'lishi mumkin. Python iteratorlarni yaratish uchun ancha ixcham sintaksisni taqdim etadi: generatorlar.
Generator - bu `yield` kalit so'zidan foydalanadigan funksiya. Siz generator funksiyasini chaqirganingizda, u kodni ishga tushirmaydi. Buning o'rniga, u to'liq huquqli iterator bo'lgan generator ob'ektini qaytaradi.
Keling, `CountUpTo` misolimizni generator sifatida qayta yozamiz:
Kod:
def count_up_to_generator(max_num):
"""1 dan max_num gacha sonlarni beradigan generator funksiyasi."""
print("Generator ishga tushirildi...")
current = 1
while current <= max_num:
yield current # Shu yerda to'xtaydi va qiymatni qaytaradi
current += 1
print("Generator tugadi.")
# Uni qanday ishlatish kerak
counter_gen = count_up_to_generator(3)
for number in counter_gen:
print(f"For sikli qabul qildi: {number}")
Qarang, bu qanchalik sodda! `yield` kalit so'zi bu yerdagi sehrdir. `yield` ga duch kelinganda, funksiyaning holati muzlatiladi, qiymat chaqiruvchiga yuboriladi va funksiya to'xtaydi. Keyingi safar generator ob'ektida `__next__` chaqirilganda, funksiya o'zi to'xtagan joydan bajarilishni davom ettiradi, toki u boshqa `yield` ga duch kelguncha yoki funksiya tugaguncha. Funksiya tugagach, siz uchun avtomatik ravishda `StopIteration` ko'tariladi.
Sahna ortida Python avtomatik ravishda `__iter__` va `__next__` metodlariga ega ob'ekt yaratdi. Generatorlar ko'pincha amaliyroq tanlov bo'lsa-da, asosiy protokolni tushunish disk raskadrovka, murakkab tizimlarni loyihalash va Python-ning asosiy mexanikasi qanday ishlashini qadrlash uchun muhimdir.
Eng Yaxshi Amaliyotlar va Umumiy Xatolar
Iterator protokolini amalga oshirayotganda, umumiy xatolardan qochish uchun ushbu ko'rsatmalarga rioya qiling.
Eng Yaxshi Amaliyotlar
- Iterable va Iteratorni Ajrating: Bir nechta o'tishni qo'llab-quvvatlashi kerak bo'lgan har qanday konteyner ob'ekti uchun har doim iteratorni alohida klassda amalga oshiring. Konteynerning `__iter__` metodi har safar iterator klassining yangi nusxasini qaytarishi kerak.
- Har doim `StopIteration`ni Ko'taring: `__next__` metodi tugashni bildirish uchun ishonchli tarzda `StopIteration` ni ko'tarishi kerak. Buni unutish cheksiz sikllarga olib keladi.
- Iteratorlar iterable bo'lishi kerak: Iteratorning `__iter__` metodi har doim `self` ni qaytarishi kerak. Bu iteratorni iterable kutilgan har qanday joyda ishlatish imkonini beradi.
- Soddalik uchun Generatorlarni Afzal Ko'ring: Agar sizning iterator mantig'ingiz sodda bo'lsa va bitta funksiya sifatida ifodalanishi mumkin bo'lsa, generator deyarli har doim toza va o'qilishi osonroq bo'ladi. Iterator ob'ektining o'zi bilan yanada murakkab holat yoki metodlarni bog'lash kerak bo'lganda to'liq iterator klassidan foydalaning.
Umumiy Xatolar
- Tugatib Bo'linadigan Iterator Muammosi: Muhokama qilinganidek, ob'ekt o'zining iteratori bo'lganda, uni faqat bir marta ishlatish mumkinligini yodda tuting. Agar siz bir necha marta iteratsiya qilishingiz kerak bo'lsa, siz yoki yangi nusxa yaratishingiz yoki ajratilgan iterable/iterator naqshidan foydalanishingiz kerak.
- Holatni Unutish: `__next__` metodi iteratorning ichki holatini o'zgartirishi kerak (masalan, indeksni oshirish yoki ko'rsatkichni oldinga siljitish). Agar holat yangilanmasa, `__next__` bir xil qiymatni qayta-qayta qaytaradi, bu esa ehtimol cheksiz siklga olib keladi.
- Iteratsiya Paytida To'plamni O'zgartirish: Iteratsiya paytida to'plamni o'zgartirish (masalan, uning ustida iteratsiya qilayotgan `for` sikli ichida ro'yxatdan elementlarni o'chirish) oldindan aytib bo'lmaydigan xatti-harakatlarga, masalan, elementlarni o'tkazib yuborishga yoki kutilmagan xatolarni keltirib chiqarishga olib kelishi mumkin. Agar siz asl nusxani o'zgartirishingiz kerak bo'lsa, to'plamning nusxasi ustida iteratsiya qilish odatda xavfsizroqdir.
Xulosa
Iterator protokoli, o'zining oddiy `__iter__` va `__next__` metodlari bilan, Python-da iteratsiyaning asosidir. Bu tilning dizayn falsafasining isboti: kuchli va murakkab xatti-harakatlarni ta'minlaydigan oddiy, izchil interfeyslarni afzal ko'rish. Ketma-ket ma'lumotlarga kirish uchun universal shartnoma taqdim etish orqali, protokol `for` sikllari, komprehenshnlar va son-sanoqsiz boshqa vositalarga o'z tilida gapirishni tanlagan har qanday ob'ekt bilan uzluksiz ishlash imkonini beradi.
Ushbu protokolni o'zlashtirib, siz Python ekotizimida birinchi darajali fuqarolar bo'lgan o'zingizning ketma-ketlikka o'xshash ob'ektlaringizni yaratish qobiliyatini ochdingiz. Endi siz ma'lumotlarni dangasa ravishda qayta ishlash orqali xotirani tejaydigan, standart Python sintaksisi bilan toza integratsiyalashgan holda intuitivroq va natijada kuchliroq bo'lgan klasslarni yoza olasiz. Keyingi safar `for` siklini yozganingizda, bir lahza to'xtab, yuzaning ostida sodir bo'layotgan `__iter__` va `__next__`ning nafis raqsini qadrlang.